#ifndef REG_MACROS_H
#define REG_MACROS_H

/**************************************************************************
 MISRA RULE 45 VIOLATION:Cast from int to pointer or pointer to int. Macro 
 like functions are used to reduce the code complexity. Thus fixed address
 are typecasted to pointer. Wherever these macros are used the same violation 
 is also present.  
 **************************************************************************/
 
/* Read/Write/Set/Clear Operation Macros */
#define REG_WRITE32(address, value)       (*(uint32*)(address) = (value))
#define REG_READ32(address)               (*(volatile uint32*)(address))

#define REG_WRITE16(address, value)       (*(uint16*)(address) = (value))
#define REG_READ16(address)               (*(volatile uint16*)(address))

#define REG_WRITE8(address, value)       (*(uint8*)(address) = (value))
#define REG_READ8(address)               (*(volatile uint8*)(address))
                          
#define REG_AWRITE32(address, i, value)    (REG_WRITE32((address)+((uint32)(i)<<2U), (value)))
#define REG_AREAD32(address, i)            (REG_READ32 ((address)+((uint32)(i)<<2U)))

#define REG_AWRITE16(address, i, value)    (REG_WRITE16((address)+((uint32)(i)<<1U), (value)))
#define REG_AREAD16(address, i)            (REG_READ16 ((address)+((uint32)(i)<<1U)))

#define REG_AWRITE8(address, i, value)     (REG_WRITE8 ((address)+(uint32)(i), (value)))
#define REG_AREAD8(address, i )            (REG_READ8  ((address)+(uint32)(i)))

/*-------------- Read/Write/Set/Clear Operation Macros ------------------*/
#define REG_BIT_SET(address, mask)      (*(volatile uint32*)(address) |= ((uint32)(mask)))
#define REG_BIT_CLEAR(address, mask)    (*(volatile uint32*)(address) &= ((uint32)~(mask)))
#define REG_BIT_SET16(address, mask)      (*(volatile uint16*)(address) |= (mask))
#define REG_BIT_CLEAR16(address, mask)    (*(volatile uint16*)(address) &= ((uint16)~(mask)))
#define REG_BIT_SET8(address, mask)      (*(volatile uint8*)(address) |= ((uint8)(mask)))
#define REG_BIT_CLEAR8(address, mask)    (*(volatile uint8*)(address) &= ((uint8)~(mask)))
#define REG_RMW16(address,mask,value)	(*(volatile uint16*)(address) = ((REG_READ16(address) & ((uint16)~(mask))) | ((uint16)(value))))
#define REG_RMW(address, mask, value)   (*(volatile uint32*)(address) = ((REG_READ32(address) & ((uint32)~(mask)) | (value)))
#define REG_RMWE(address, mask, value)   (*(volatile uint32*)(address) = ((REG_READ32(address) & ((uint32)~(mask)) | (mask & value))))

#endif
